package browser;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.URI;
import java.net.URISyntaxException;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * Browser zum Darstellen von Inhalten, deren
 * Addresse in einer Addresszeile eingegeben werden
 * kann.
 * <p>
 * Um eine Datei mit dem Browser anzuzeigen, wird die
 * Adresse der Datei in die Adresszeile eingegeben.
 * Anschließen muss nur die Enter-Taste gedrückt werden und 
 * die Datei wird im Browser angezeigt, wenn Protokoll und
 * Dateityp vom Browser unterstützt werden.* 
 * <p>
 * Unterstützte Protokolle des Browsers:
 * <pre>
 * http
 * ftp
 * file
 * </pre>
 * Unterstützt Dateitypen des Browsers:
 * <pre>
 * text/plain
 * text/html (unformatiert)
 * content/unknown (Inhalt wird als Text ausgegebeb)
 * image/gif
 * application/x-shar (Shellskript)
 * application/x-sh (Shellskript)
 * application/x-shellscript (Shellskript)
 * </pre>
 * 
 * @author Pierre Ahrendt und Richard Wilhelm
 * @version 1.0 Jan 11, 2009
 */
public class Browser extends JFrame implements KeyListener {
    /**
     * auto-generated serialUID.
     */
    private static final long serialVersionUID = -6036156081786585122L;

    /**
     * Adresszeile, in die die URLs der
     * Dateien einngegeben werden können. 
     */
    private JTextField address;

    /**
     * Komponente, die den Inhalt der Dateien
     * anzeigt.
     */
    private JComponent content;

    /**
     * Liste der unterstützten Protokolle.
     */
    private final String[] PROTOCOL_SUPPORT = new String[] {
	    "file", 
	    "ftp", 
	    "http"};
    
    /**
     * Konstruktor des Browser baut weitgehend die GUI
     * mit Adresszeile und Startseite.
     * <p>
     * Auf der Adresszeile wird ein Keylistener gestartet
     * der die Eingabe weiterverarbeitet.
     */
    public Browser() {
	// Titel des Fensters
	this.setTitle("JBrowser");
	
	// StartGröße des Fensters setzen
	this.setPreferredSize(new Dimension(640, 480));
	this.address = new JTextField();

	// Startseite mit dem Inhalt
	// "Hello World!" erzeugen
	this.content = ComponentFactory.createTextComponent("Hello World!");
	
	
	// Listener um auf das Drücken der 
	// Enter-Taste zu reagieren
	address.addKeyListener(this);

	this.add(address, BorderLayout.NORTH);
	this.add(content);
	this.pack();

	// Programm beendet, wenn Fester geschlossen wird
	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**  
     * KeyListener reagiert auf das Drücken der
     * Enter-Taste.
     * <p>
     * Die eingegeben Addresse wird in eine URI umgewandelt.
     * <br />
     * Danach wird überprüft, ob das Protokoll unterstützt wird.
     * <p>
     * Wird das Protokoll unterstüzt, dann wird Inhalt über
     * die ComponentFactory erzeugt, sonst wird
     * eine Fehlermeldung zurückgegeben.
     * 
     * {@inheritDoc}
     * */
    public void keyPressed(KeyEvent e) {
	if (e.getKeyCode() == KeyEvent.VK_ENTER) {
	    // Debug-Output für Addresszeile
	    System.out.println(this.address.getText());
	    
	    // Addresse in URI umwandeln
	    URI uri = null;
	    try {
		uri = new URI(this.address.getText());
	    } catch (URISyntaxException e1) {
		this.updateContent(ComponentFactory.createErrorComponent(
			e1.getMessage()));
		return;
	    }
	    
	    // Überprüfung, ob das angegebene Protokoll
	    // unterstützt wird
	    if (!this.isProtocolSupported(uri)) {
		this.updateContent(ComponentFactory.createErrorComponent(
			"Unbekannte Protokoll: " + uri.toASCIIString()));
		return;
	    }
	    
	    // Komponente erzeugen
	    updateContent(ComponentFactory.createComponent(uri));
	}
    }

    /** {@inheritDoc} */
    public void keyReleased(KeyEvent e) {   }

    /** {@inheritDoc} */
    public void keyTyped(KeyEvent e) { }
    
    /**
     * Methode zum Aktualisieren der Swing-Komponente, die
     * den Inhalt des Browsers darstellt.
     * 
     * @param content neuer Inhalt der angezeigt werden soll.
     */
    private void updateContent(JComponent content) {
	this.remove(this.content);
	JScrollPane scroll = new JScrollPane(content);
	this.content = scroll;	
	this.add(this.content);
	this.validate();
    }
    
    /**
     * Methode zum Überprüfen, ob die angegebene Addresse
     * eines der unterstützten Protokolle enthält.
     * <p>
     * Unterstützte Protokolle:
     * <pre>
     * http
     * ftp
     * file
     * </pre>
     * 
     * @param uri Addresse bei der das Protokoll überprüft werden soll.
     * @return <code>true</code>, wenn das Protokoll unterstützt wird, sonst
     * 		<code>false</code>
     */
    private boolean isProtocolSupported(URI uri) {
	// wenn kein Protokoll angegeben wird,
	// dann kann die Datei auch nicht verarbeitet werden
	if (uri.getScheme() == null) {
	    return false;
	}
	    
	for (String p : this.PROTOCOL_SUPPORT) {
	    if (p.equals(uri.getScheme().toLowerCase())) {
		return true;
	    }
	}
	    
	return false;
    }
    
    /**
     * Programm startet den Browser.
     * 
     * @param args werden nicht benötig.
     */
    public static void main(String[] args) {
	Browser jb = new Browser();
	jb.setVisible(true);
    }
}
